package main

import (
	"context"
	"github.com/ethmonitor/cmd"
	go_logger "github.com/ethmonitor/go-logger"
	"github.com/ethmonitor/service"
	"github.com/urfave/cli/v2"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"net/http"
	"os"
	"os/signal"
	"syscall"
)

func main() {
	app := &cli.App{
		Name:                   "node monitor",
		UseShortOptionHandling: true,
		Version:                FormatVersion(),
		Flags:                  cmd.RootFlags,
		Action:                 appRun,
	}
	err := app.Run(os.Args)
	if err != nil {
		go_logger.Logger.Error("service running failed", zap.String("service running failed", err.Error()))
	}
}

func appRun(ctx *cli.Context) error {
	sctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	watchAddress := ctx.StringSlice("address")
	if len(watchAddress) > 0 {
		cmd.DefaultConfig.WatchAddr = watchAddress
	}

	level := ctx.Int("debug.level")
	if level > int(zapcore.DebugLevel) || level <= int(zapcore.FatalLevel)+1 {
		go_logger.LogLevel = zapcore.Level(level - 1)
	}

	go_logger.LogInit()
	defer go_logger.Logger.Sync()

	pprof := ctx.Bool("go.pprof")
	if pprof {
		go func() {
			go_logger.Logger.Info("golang pprof", zap.String("running url", "http://localhost:10000"))
			go_logger.Logger.Sugar().Info(http.ListenAndServe("localhost:10000", nil))
		}()
	}

	go_logger.Logger.Sugar().Info("App running config ", cmd.DefaultConfig)

	server := service.NewService(sctx, &cmd.DefaultConfig)
	if err := server.Start(); err != nil {
		go_logger.Logger.Error("App run failed", zap.Error(err))
		return err
	}

	appWait(cancel)
	server.Close()

	return nil
}

func appWait(cancelFunc context.CancelFunc) {
	sigs := make(chan os.Signal, 1)
	done := make(chan bool, 1)

	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		sig := <-sigs
		go_logger.Logger.Info(sig.String())
		done <- true
	}()

	go_logger.Logger.Info("waiting signal ...")
	<-done
	go_logger.Logger.Info("app quit ...")
	cancelFunc()
}
